package com.myfojing.mycloud;


import android.content.Context;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.HashMap;

import io.realm.Realm;
import io.realm.RealmObject;
import io.realm.annotations.Ignore;
import io.realm.annotations.PrimaryKey;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class Sensirion extends RealmObject implements Parcelable {
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        @Override
        public Sensirion createFromParcel(Parcel source) {
            return new Sensirion(source);
        }

        @Override
        public Sensirion[] newArray(int size) {
            return new Sensirion[size];
        }
    };

    private String title = "node";
    private String description;
    private String type = "sht1x";
    private String PIN;
    private String ip = "192.168.4.1";
    private String nm = "255.255.255.0";
    private String gw = "192.168.4.1";
    private String port = "80";

    @PrimaryKey
    private String mac;

    // 通讯
    @Ignore
    private final String TAG = "我的传感器";
    @Ignore
    private OkHttpClient client = new OkHttpClient();
    @Ignore
    private HashMap<String, String> map = new HashMap<>();
    @Ignore
    private SensirionListener listener;
    // data
    @Ignore
    private float temp;
    @Ignore
    private float hum;
    @Ignore
    private long timestamp;
    @Ignore
    private boolean online;
    @Ignore
    private int elapsed;
    @Ignore
    private int sample_interval;
    @Ignore
    private int record_interval;
    @Ignore
    private Context context;

    /* 构造 */
    public Sensirion() {
        this.listener = null;
    }

    Sensirion(String ip, String port) {
        this.ip = ip;
        this.port = port;
        //this.type = type;
        this.listener = null;
    }

    public Sensirion(String title, String description, String type, String ip, String port, String mac) {
        this.title = title;
        this.description = description;
        this.type = type;
        this.ip = ip;
        this.port = port;
        this.mac = mac;
    }

    private Sensirion(Parcel in) {
        title = in.readString();
        description = in.readString();
        type = in.readString();
        ip = in.readString();
        nm = in.readString();
        gw = in.readString();
        port = in.readString();
        mac = in.readString();
    }

    void setSensirionListener(SensirionListener listener) {
        this.listener = listener;
    }

    /* 请求 */
    private void myRequest() {
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        JSONObject json = new JSONObject();
        try {
            // 遍历
            for (String key : map.keySet()) {
                json.put(key, map.get(key));
            }

        } catch (JSONException e) {
            Log.d(TAG, "Json error");
        }

        RequestBody body = RequestBody.create(JSON, json.toString());

        final Request request = new Request.Builder()
                .url(String.format("http://%s:%s", this.ip, this.port))
                .post(body)
                .build();

        Call call = client.newCall(request);
        // 请求加入调度(发送请求)
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                //Log.d(TAG, e.toString());
                online = false;
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("success", false);
                    if (listener != null) {
                        listener.onDataReady(jsonObject);
                    }
                } catch (JSONException e_2) {
                    e_2.printStackTrace();
                }
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                if (response.code() == 200) {
                    try {
                        String body = response.body().string();
                        JSONObject jsonObject = new JSONObject(body);
                        // 返回的命令
                        String cmd = jsonObject.getString("cmd");
                        // 读温湿度
                        if (cmd.equals("read_th") && jsonObject.getBoolean("success")) {
                            int temperature = jsonObject.getInt("temp");
                            int humidity = jsonObject.getInt("hum");
                            timestamp = jsonObject.getLong("time");
                            switch (jsonObject.getString("type")) {
                                case "sht1x_v3":
                                    cal_sht10(temperature, humidity);
                                    break;
                            }  // switch

                            // save
                            elapsed += sample_interval;
                            if (elapsed >= record_interval) {
                                elapsed = 0;
                                // 保存到record
                                // 检查时间
                                long deltT = System.currentTimeMillis() / 1000 - timestamp;
                                if (deltT >= 86400) {
                                    // 取本地时间
                                    timestamp = System.currentTimeMillis() / 1000;
                                    MyRecord record = new MyRecord(mac, temp, hum, timestamp);
                                    // save
                                    Realm realm = Realm.getDefaultInstance();
                                    realm.executeTransaction(new Realm.Transaction() {
                                        @Override
                                        public void execute(Realm realm) {
                                            MyRecord record = realm.createObject(MyRecord.class);
                                            record.setMac(mac);
                                            record.setTemp(temp);
                                            record.setHum(hum);
                                            record.setCreated_at(timestamp);
                                        }
                                    });
                                }
                            }
                            // 发送新广播
                            sendMessage(temp, hum, mac, timestamp);
                            // outer if

                        } else {
                            // 其他， 直接返回
                            if (listener != null) {
                                listener.onDataReady(jsonObject);
                            }
                        }
                        // 节点状态
                        online = true;
                    } catch (NullPointerException | JSONException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("success", false);
                        if (listener != null) {
                            listener.onDataReady(jsonObject);
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                //send_data(body);
            }
        });
    }

    /* 通讯 */

    // 命令
    void read(String cmd) {
        map.clear();
        map.put("cmd", cmd);
        myRequest();
    }

    void write(String cmd, String data) {
        map.clear();
        map.put("cmd", cmd);
        map.put("data", data);
        myRequest();
    }
    // say hello
    void say_hello() {
        map.clear();
        map.put("cmd", "say_hello");
        myRequest();
    }

    void read_all() {
        map.clear();
        map.put("cmd", "read_all");
        myRequest();
    }

    // 读wifi
    void read_wifi() {
        map.clear();
        map.put("cmd", "read_wifi");
        myRequest();
    }

    // 列出ap
    void list_ap() {
        map.clear();
        map.put("cmd", "list_ap");
        myRequest();
    }

    // 写wifi
    void write_wifi(String ssid, String password) {
        map.clear();
        map.put("cmd", "write_wifi");
        map.put("ssid", ssid);
        map.put("password", password);
        myRequest();
    }

    // 读取温湿度
    void read_th(Context context, int sample_interval, int record_interval) {
        this.context = context;
        this.sample_interval = sample_interval;
        this.record_interval = record_interval;

        map.clear();
        map.put("cmd", "read_th");
        myRequest();
    }

    HashMap<String, Float> get_th() {
        HashMap<String, Float> t = new HashMap<>();
        t.put("hum", hum);
        t.put("temp", temp);
        return t;
    }

    // 读设备
    void read_device() {
        map.clear();
        map.put("cmd", "read_device");
        myRequest();
    }

    // 写设备
    void write_device(String data) {
        map.clear();
        map.put("cmd", "write_device");
        map.put("data", data);
        myRequest();
    }

    // 写网络
    void write_network(String data) {
        map.clear();
        map.put("cmd", "write_network");
        map.put("data", data);
        myRequest();
    }

    // 同步时间
    void set_time(String timestamp) {
        map.clear();
        map.put("cmd", "set_time");
        map.put("data", timestamp);
        myRequest();
    }


    /* 计算 */
    private void cal_sht10(int t, int h) {
        float C1 = -2.0468f;
        float C2 = 0.0367f;
        float C3 = -0.0000015955f;
        float T1 = 0.01f;
        float T2 = 0.00008f;

        float rh_lin = 0;

        this.temp = t * 0.01f - 40.1f;
        rh_lin = C3 * h * h + C2 * h + C1;
        this.hum = (this.temp - 25) * (T1 + T2 * h) + rh_lin;

        this.temp = (float) Math.round(this.temp * 10) / 10;
        this.hum = (float) Math.round(this.hum * 10) / 10;

        if (this.hum > 100) this.hum = 100;
        if (this.hum < 0.1) this.hum = 0.1f;

    }

    // getter and setter
    public String getMac() {
        return mac;
    }
/* 属性 */

    public void setMac(String mac) {
        this.mac = mac;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getPort() {
        return port;
    }

    public void setPort(String port) {
        this.port = port;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getNm() {
        return nm;
    }

    public void setNm(String nm) {
        this.nm = nm;
    }

    public String getGw() {
        return gw;
    }

    public void setGw(String gw) {
        this.gw = gw;
    }

    public String getTemp() {
        return Float.toString(temp);
    }

    public void setTemp(float temp) {
        this.temp = temp;
    }

    public String getHum() {
        return Float.toString(hum) + "%";
    }

    public void setHum(float hum) {
        this.hum = hum;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getPIN() {
        return PIN;
    }

    public void setPIN(String PIN) {
        this.PIN = PIN;
    }

    public boolean isOnline() {
        return online;
    }

    public void setElapsed(int elapsed) {
        this.elapsed = elapsed;
    }

    // 打包
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(title);
        dest.writeString(description);
        dest.writeString(type);
        dest.writeString(ip);
        dest.writeString(nm);
        dest.writeString(gw);
        dest.writeString(port);
        dest.writeString(mac);
    }

    // 发送广播
    private void sendMessage(float t, float h, String mac, long timestamp) {
        Intent intent = new Intent("event_rh");
        intent.putExtra("t", t);
        intent.putExtra("h", h);
        intent.putExtra("mac", mac);
        intent.putExtra("timestamp", timestamp);
        //Log.d(TAG, "发送:" + Integer.toString(sample_interval) + ", " + getTime());
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }

    // interface
    interface SensirionListener {
        void onDataReady(JSONObject data);
    }

    // end
}
